package com.iris.live.services.services.impl;

import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.iris.live.services.common.LineContextUtil;
import com.iris.live.services.common.StringUtils;
import com.iris.live.services.common.config.Constants;
import com.iris.live.services.common.reconsitution.DefaultValueConstant;
import com.iris.live.services.common.reconsitution.StockForecastUtils;
import com.iris.live.services.data.models.MarketAnnualBudgetModel;
import com.iris.live.services.data.models.MarketIntegratedReportModel;
import com.iris.live.services.data.models.ReportConfig;
import com.iris.live.services.data.models.用户Model;
import com.iris.live.services.data.repositories.*;
import com.iris.live.services.models.PageData;
import com.iris.live.services.models.ResultData;
import com.iris.live.services.report.data.IReportDataService;
import com.iris.live.services.report.data.IReportDataSource;
import com.iris.live.services.report.data.IReportRowHandler;
import com.iris.live.services.report.data.ReportContext;
import com.iris.live.services.report.handlers.FinancialFunnelRowHandler;
import com.iris.live.services.report.handlers.SaleManagementRowHandler;
import com.iris.live.services.services.FinanceService;
import com.iris.live.services.services.InsuranceService;
import com.iris.live.services.services.MgtReportService;
import com.iris.live.services.vo.report.MarketIntegratedVO;
import com.iris.live.services.vo.report.StockForecastVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.iris.live.services.common.LineContextUtil.getReportConifTree;

/**
 * Created by lusong on 2016/12/9.
 */
@Service
@Transactional
public class MgtReportServiceImpl implements MgtReportService {
    /********************************************和前端定义接口测试方法  无效，完成后可以删除*****************************************************/
    private static String[] groups={"集团总部","大北京","北一区","北二区","北三区","西区","大上海","东一区","东二区","南区"};
    private static String[] carType={"MM","MB","AMG","MB+MM+AMG","SMART","VAN","DENZA","总计"};

    private Logger logger = LoggerFactory.getLogger(MgtReportServiceImpl.class);
    @Autowired
    private IReportDataService reportDataService;

    @Resource(name = "SaleManagementDataSource")
    private IReportDataSource saleManagementDataSource;

    @Resource(name = "InsManagementDataSource")
    private IReportDataSource insManagementDataSource;

    @Resource(name = "FinanceManagementDataSource")
    private IReportDataSource financeManagementDataSource;

    @Resource(name = "ClueManagementDataSource")
    private IReportDataSource clueManagementDataSource;

    @Resource(name = "FinDefeatedResonRptDataSource")
    private IReportDataSource finDefeatedResonRptDataSource;

    @Resource(name = "InsuranceCompanyDataSource")
    private IReportDataSource insuranceCompanyDataSource;

    @Resource(name = "SalesDailyReportSource")
    private IReportDataSource SalesDailyReportSource;

    @Autowired
    private FinanceService financeService;

    @Resource(name = "SalesFunnelDataSource")
    private IReportDataSource salesFunnelDataSource;
    @Resource(name = "SalesFunnelRowHandler")
    private IReportRowHandler SalesFunnelRowHandler;
    @Resource(name = "FinanceFunnelDataSource")
    private IReportDataSource financeFunnelDataSource;

    @Resource(name = "InsDefeatedResonRptDataSource")
    private IReportDataSource insDefeatedResonRptDataSource;

    @Autowired
    private InsuranceService insuranceService;

    @Resource(name = "AfterMarketBusinessDataSource")
    private IReportDataSource afterMarketBusinessDataSource;

    @Resource(name = "AfterMarketProductInstallation")
    private IReportDataSource afterMarketProductInstallation;

    @Resource(name = "StockForecastDataSource")
    private IReportDataSource stockForecastDataSource;

    @Resource(name = "CRMGroupSurveyReportSource")
    private IReportDataSource crmGroupSurveyReportSource;

    @Autowired
    private MarketAnnualBudgetRepository marketAnnualBudgetRepository;

    @Autowired
    private MarketIntegratedReportRepository marketIntegratedReportRepository;

    @Autowired
    private Lsh经销商表Repository lsh经销商表Repository;

    @Autowired
    private MgtReportRepository marketIntegrateRepository;

    @Autowired
    private 用户Repository userRepository;


    /**
     * 销售管理报表数据获取
     *
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getSalesReport(Map info) throws Exception {
        info.put("reportCode", "销售管理报表");

        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);

        //获取报表指标树:Y轴维度
        List<ReportConfig> configs = getReportConifTree("销售管理报表");

        context.setHandler(new SaleManagementRowHandler());
        List resultList = reportDataService.getData(context, configs, saleManagementDataSource);
        return resultList;
    }

    /**
     * 通过用户登录的账号，获取用户的类型
     * 根据角色不同 ROS零售目标 的取值不同
     * userType = 1,集团角色（查看集团或大区） 取 集团--大区建议目标；
     * userType = 2,集团角色（查看经销商） 取 集团--大区的建议目标再分解到经销商的目标；
     * userType = 3,大区角色（查看大区） 取 集团--大区建议目标（region_sale_target_group--时间维度） 或 集团--大区的建议目标再分解到经销商的目标（dealer_sale_target_group--组织架构纬度） 和 大区--经销商设置目标（dealer_sale_target）；
     * userType = 4,大区角色（查看经销商） 取 集团--大区的建议目标再分解到经销商的目标 和 大区--经销商设置目标；
     * userType = 5,PMA角色（查看经销商） 取 大区--经销商设置目标；
     * @param info
     */
    private void getUsernameType (Map info) {
        if (StringUtils.isNullOrBlank(info.get("fr_username"))) {
            return;
        }
        String username = info.get("fr_username").toString(), role = null;
        if ("Admin".equals(username)) {
            role = "集团";
        } else {
            用户Model model = userRepository.findOne(username);
            if (model != null) {
                role = model.get角色();
            }
        }
        boolean paramRegion = StringUtils.isNullOrBlank(info.get("selRegionCode"))
                || "全部".equals(info.get("selRegionCode").toString())
                || "all".equalsIgnoreCase(info.get("selRegionCode").toString()),
                paramPMA = StringUtils.isNullOrBlank(info.get("selPMACode"))
                        || "全部".equals(info.get("selPMACode").toString())
                        || "all".equalsIgnoreCase(info.get("selPMACode").toString()),
                paramDealer = StringUtils.isNullOrBlank(info.get("selDealerCode"))
                        || "全部".equals(info.get("selDealerCode").toString())
                        || "all".equalsIgnoreCase(info.get("selDealerCode").toString());
        if ("集团".equals(role)) {
            if (paramRegion && paramDealer && paramPMA) {
                info.put("userType", "0");
            } else if (paramDealer && paramPMA) {
                info.put("userType", "1");
            } else {
                info.put("userType", "2");
            }
        } else if ("大区".equals(role)) {
            if (paramDealer && paramPMA) {
                info.put("userType", "3");
            } else {
                info.put("userType", "4");
            }
        } else {
            info.put("userType", "5");
        }
    }

    /**
     * 金融报表数据获取
     *
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getFinanceReport(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);

        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = getReportConifTree("金融报表");

        return reportDataService.getData(context, configs, financeManagementDataSource);
    }

    /**
     * 保险报表数据获取
     *
     * @param info
     * @return
     * @throws Exception
     */

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getInsReport(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTree("保险报表");
        return reportDataService.getData(context, configs, insManagementDataSource);
    }

    /**
     * 保险战败原因分析
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getInsDefeatedResonRpt(Map info) throws Exception {
        List mode = insuranceService.getInsDefeatedResonRpt();
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context = LineContextUtil.getReportContext(info);
        //报表输出值是否是率 true 是  false 否
        context.setRatio(true);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = new ArrayList<>();
        ReportConfig reConfig = new ReportConfig();
        reConfig.setReportCode("保险战败原因分析");
        reConfig.setAinCode("保险战败原因分析");
        reConfig.setParentCode("0");
        reConfig.setCategory("oneIndex");
        for (int i = 0; i < mode.size() + 1; i++) {
            ReportConfig config = new ReportConfig();
            config.setReportCode("保险战败原因分析");
            config.setParentCode("保险战败原因分析");
            config.setCategory("defeatedReson");
            config.setMatchKey("战败原因");
            config.setValueKey("数量");
            config.setMatchItem(1);
            config.setMatcher(1);
            if (i == mode.size()) {
                if(StringUtils.isNotNullOrBlank(info.get("displayRow")) && "all".equals(info.get("displayRow"))) {
                    config.setAinCode("Total");
                    config.setText("Total");
                    config.setProjectNameOrder("1000");
                }
            } else {
                Map map = (Map) mode.get(i);
                config.setAinCode(map.get("战败原因").toString());
                config.setText(map.get("战败原因").toString() + ("启用".equals(map.get("状态")) ? "" : "*"));
                //如果是停用的状态 则放回“999”给前段，好判断 启用和停用的区别
                if ("停用".equals(map.get("状态").toString())) {
                    config.setProjectNameOrder("999");
                } else {
                    config.setProjectNameOrder((i + 1) + "");
                }
            }
            List temp = reConfig.getChildConfigs();
            if (temp == null) {
                temp = new ArrayList<>();
                reConfig.setChildConfigs(temp);
            }
            temp.add(config);
        }
        configs.add(reConfig);
        int size=configs.size();
        List resultList =  reportDataService.getData(context, configs, insDefeatedResonRptDataSource);
        if (resultList != null) {
            for (Object o : resultList) {
                Map map = (Map) o;
                if ("Total".equals(map.get("defeatedResonName"))) {
                    map.put("value", "100.0%");
                }
            }
        }
        return resultList;
    }

    /**
     * 金融战败
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getFinDefeatedResonRpt(Map info ) throws Exception{
        List modelList=financeService.getFinDefeatedReson();
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        context.setRatio(true);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs=new ArrayList<>();
        ReportConfig c=new ReportConfig();
        c.setReportCode("金融战败原因分析");
        c.setAinCode("金融战败原因分析");
        c.setParentCode("0");
        c.setCategory("oneIndex");
        for (int i=0;i<modelList.size() + 1;i++){
            ReportConfig config=new ReportConfig();
            config.setReportCode("金融战败原因分析");
            config.setParentCode("金融战败原因分析");
            config.setCategory("defeatedReson");
            config.setMatchKey("战败原因");
            config.setValueKey("数量");
            config.setMatchItem(1);
            config.setMatcher(1);
            if (i == modelList.size()) {
                if(StringUtils.isNotNullOrBlank(info.get("displayRow")) && "all".equals(info.get("displayRow"))) {
                    config.setAinCode("Total");
                    config.setText("Total");
                    config.setProjectNameOrder("1000");
                }
            } else {
                Map m=(Map) modelList.get(i);
                config.setAinCode(m.get("战败原因").toString());
                config.setText(m.get("战败原因").toString() + ("启用".equals(m.get("状态"))? "" : "*"));
                //如果是停用的状态 则返回“999”给前端，好判断 启用和停用的区别
                if ("停用".equals(m.get("状态").toString())){
                    config.setProjectNameOrder("999");
                }else {
                    config.setProjectNameOrder((i+1)+"");
                }
            }

            List temp= c.getChildConfigs();
            if(temp==null){
                temp=new ArrayList<>();
                c.setChildConfigs(temp);
            }
            temp.add(config);
        }
        configs.add(c);
        int size=configs.size();
        List resultList = reportDataService.getData(context, configs, finDefeatedResonRptDataSource);
        if (resultList != null) {
            for (Object o : resultList) {
                Map map = (Map) o;
                if ("Total".equals(map.get("defeatedResonName"))) {
                    map.put("value", "100.0%");
                }
            }
        }
        return resultList;
    }


    /**
     * DCC渠道线索报表
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getDCCChannelClue(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = getReportConifTree("DCC渠道线索报表");
        return reportDataService.getData(context, configs, clueManagementDataSource);
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getAfterMarketBusiness(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = getReportConifTree("后市场业务报表");
        List<Map> list = reportDataService.getData(context, configs, afterMarketBusinessDataSource);
        replaceAfterMarketReportList(list);
        return list;
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getAfterMarketProductInstallation(Map info) throws Exception{
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        context.setOrderName("project");
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = getReportConifTree("后市场产品加装率报表");
        List<Map> list = reportDataService.getData(context, configs, afterMarketProductInstallation);
        replaceAfterMarketReportList(list);
        return list;
    }

    @Override
    public List getSalesFinanceReoprt(Map info) throws Exception{
        List list = marketIntegrateRepository.getSalesFinanceReoprt(info);
        return list;
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getInsuranceSummary(Map info) throws Exception{
        info.put(Constants.FRAMEWORK_KEY,LineContextUtil.orgLine);
        info.put(Constants.DEALER_KEY,"");
        List mode = insuranceService.getInsuranceCompany();
        //构造context ：包括权限等级，x轴的维度（组织架构维度）
        ReportContext context = LineContextUtil.getReportContext(info);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = new ArrayList<>();
        ReportConfig reConfig = new ReportConfig();
        for (int i = 0; i < mode.size() + 1; i++) {
            ReportConfig config = new ReportConfig();
            config.setReportCode("保险合作机构汇总");
            config.setCategory("insurance");
            config.setMatchKey("保险公司");
            config.setValueKey("合作数量");
            config.setDataType("int");
            config.setMatchItem(1);
            config.setMatcher(1);
            if(i == mode.size()){
                config.setAinCode("经销商总数");
                config.setText("经销商总数");
                config.setProjectNameOrder("0");
            }else {
                Map map = (Map) mode.get(i);
                config.setAinCode(map.get("保险公司").toString());
                config.setText(map.get("保险公司").toString());
                config.setProjectNameOrder((i + 1) + "");
            }
            List temp = reConfig.getChildConfigs();
            if (temp == null) {
                temp = new ArrayList<>();
                reConfig.setChildConfigs(temp);
            }
            temp.add(config);
        }
        configs.add(reConfig);
        //数据处理
        List resultList =  reportDataService.getData(context, configs, insuranceCompanyDataSource);
        return resultList;

    }


    @Override
    @Transactional(propagation = Propagation.NEVER)
    public Map<String,Object> getStockForecast(Map info) throws Exception {
        return getTotalForm(info);
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getBuildPurchaseReportAll(Map info) throws Exception {
        return buildPurchaseReportAll(info);
    }

    /**
     * 销售毛利预测
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getGrossProfitForecastReport(Map info) throws Exception {
        return getTotalFormByGrossProfit(info);
    }


    //---------------------库存预测str----------------------
    /**
     * 获取库存预测总map
     * @param info
     * @return
     */
    private Map<String,Object> getTotalForm(Map info){
        Map<String,Object> map = Maps.newHashMap();
        //库存预测计划分为4个分开的小报表①车型订单预测②颜色选择③车款选择④采购预测
        //车型订单预测
        map.put("orderReport",buildOrderReport(info));
        //颜色选择
        map.put("colorReport",replaceMap(buildColorReport(info)));
        //车款选择
        map.put("carReport",replaceMap(buildCarReport(info)));
        //采购预测
        map.put("purchaseReport",buildPurchaseReport(info));
        return map;
    }

    private List replaceMap(List<Map> info){
        return info.stream()
                .filter(m->!m.get("displayRow").equals("总计"))
                .collect(Collectors.toList());
    }


    /**
     * crm调研报告
     * @param info
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getCRMSurveyReport(Map info) throws Exception{
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);

        String reportCode = null;
        if (!StringUtils.isNullOrBlank(info.get("resType"))) {
            String resType = info.get("resType").toString();
            if ("01".equals(resType)) {
                reportCode = "CRM_首次离店调研报告";
            } else if ("02".equals(resType)) {
                reportCode = "CRM_休眠调研报告";
            } else if ("03".equals(resType)) {
                reportCode = "CRM_战败调研报告";
            } else if ("04".equals(resType)) {
                reportCode = "CRM_NPS调研报告";
            } else {
                logger.error("crm调研报告--参数 调研类型 不在值域内，resType -- " + resType);
                return null;
            }
        } else {
            logger.error("crm调研报告--参数 调研类型 为必传参数");
            return null;
        }
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTree(reportCode);
        return reportDataService.getData(context, configs, crmGroupSurveyReportSource);
    }

    /**
     * 获取对应报表标题
     * @param formType
     * @return
     */
    private List<ReportConfig> buildReportFormTitle(int formType){
        Map<String,Object> map = Maps.newHashMap();
        String formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_ORDER_NAME;
        switch (formType){
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_ORDER_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_ORDER_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_COLOR_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_COLOR_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_CAR_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_CAR_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_PURCHASE_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_PURCHASE_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_GROSS_PROFIT_FORECAST_HIGHLIGHT_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_GROSS_PROFIT_FORECAST_HIGHLIGHT_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_GROSS_PROFIT_FORECAST_STOCK_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_GROSS_PROFIT_FORECAST_STOCK_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_FUNNEL_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_FUNNEL_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_NEW_CAR_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_NEW_CAR_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_OTHER_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_OTHER_NAME;
                break;
            case DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_TOTAL_TYPE:
                formName = DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_TOTAL_NAME;
                break;
        }
        return getReportConifTree(formName);
    }

    /**
     * 获取库存订单预测部分
     * @param info
     * @return
     */
    private List<StockForecastVo> buildOrderReport(Map info){
        String brand = String.valueOf(info.get("selBrand"));
        String carSeries = String.valueOf(info.get("selClass"));
        String carModel = String.valueOf(info.get("selType"));
        String permit = String.valueOf(userRepository.findPermitByUsername(info.get("fr_username").toString()));
        List<StockForecastVo> list = new ArrayList<StockForecastVo>();
        List<ReportConfig> configList = buildReportFormTitle(DefaultValueConstant.REPORT_FORM_STOCK_FORECAST_ORDER_TYPE);
        for (int i = 0; i < configList.size(); i ++) {
            ReportConfig config = configList.get(i);
            StockForecastVo vo = null;
            if(config.getText().equals("车型")){
                vo = new StockForecastVo(config.getText(),null,Integer.parseInt(config.getProjectNameOrder()),0,carModel,config.getReportCode());
            }else{
                vo = new StockForecastVo(config.getText(),null,Integer.parseInt(config.getProjectNameOrder()),0,StockForecastUtils.orderFormValue(config.getText(),brand,carSeries,carModel,permit),config.getReportCode());
            }
            list.add(vo);
        }
        return list;
    }

    /**
     * 获取颜色选择部分

     * @return
     */
    private List<Map> buildColorReport(Map info){
        List<Map> list = new ArrayList<Map>();
        info.put("displayType",1);
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContextByStockForecast(info,1);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTree("库存预测_颜色选择预测");
        try {
            return reportDataService.getData(context, configs, stockForecastDataSource);
        }catch(Exception e){
            logger.error("颜色选择预测数据查询异常");
        }
        return null;
    }

    /**
     * 获取车款选择部分
     * @param info
     * @return
     */
    private List<Map> buildCarReport(Map info){
        List<StockForecastVo> list = new ArrayList<StockForecastVo>();
        info.put("displayType",2);
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContextByStockForecast(info,2);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTree("库存预测_车款选择预测");
        try {
            return reportDataService.getData(context, configs, stockForecastDataSource);
        }catch(Exception e){
            logger.error("车款选择预测数据查询异常");
        }
        return null;
    }

    /**
     * 获取采购部分
     * @param info
     * @return
     */
    private List<Map> buildPurchaseReport(Map info){

        info.put("displayType",3);
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContextByStockForecast(info,3);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTreeByBuildPurchase(info);
        try {
            return reportDataService.getData(context, configs, stockForecastDataSource);
        }catch(Exception e){
            logger.error("颜色选择预测数据查询异常");
        }
        return null;
    }

    /**
     * 获取采购部分
     * @param info
     * @return
     */
    private List<Map> buildPurchaseReportAll(Map info){

        info.put("displayType",4);
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContextByStockForecast(info,3);
        //获取报表指标树　：Y轴维度
        List<ReportConfig> configs = LineContextUtil.getReportConifTreeByPermit(info);
        try {
            return reportDataService.getData(context, configs, stockForecastDataSource);
        }catch(Exception e){
            logger.error("颜色选择预测数据查询异常");
        }
        return null;
    }

    //---------------------库存预测end----------------------

    //---------------------市场月度报表start-----------------------------

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getMarketIntegratedReport(Map info) throws Exception {
        Map<String,Object> map = Maps.newHashMap();
        String permit = String.valueOf(userRepository.findPermitByUsername(info.get("username").toString()));
        info.put("permit",permit);
        //将月度市场报表切成两部部分 1.活动费用部分 2.市场成效数据
        //活动费用部分
        //map.put("expense",getMarketExpenseList(info));   暂时没有填报部分 暂时注销
        //市场成效数据
        //map.put("marketEffect",getMarketEffectList(info));
        return getMarketEffectList(info);
    }

    /**
     * 获取活动费用部分数据
     * @param info
     * @return
     * @throws Exception
     */
    private List getMarketExpenseList(Map info)throws Exception{
        return  calculateMarketExpenseList(marketIntegrateRepository.getMarketExpenseList(info),info);
    }

    /**
     * 获取市场成效数据
     * @param info
     * @return
     * @throws Exception
     */
    private List getMarketEffectList(Map info)throws Exception{
        return  marketIntegrateRepository.getMarketEffectList(info);
    }

    /**
     * 计算预算结余 方法
     * @param list
     * @param info
     * @return
     */
    private List calculateMarketExpenseList(List list ,Map info) {
        List marketAnnualBudgetList=marketIntegrateRepository.getMarketAnnualBudget(info);
        Double budgetSurplus=0d;Double factoryBudgetsurplus=0d;Double annualBudget=0d;
        if(marketAnnualBudgetList!=null&&marketAnnualBudgetList.size()!=0){
            annualBudget=(Double)((Map)marketAnnualBudgetList.get(0)).get("annual_budget");
            budgetSurplus=annualBudget;
            factoryBudgetsurplus=annualBudget;
        }
        for (Object item:list) {
            Map itemMap=(Map)item;
            budgetSurplus=budgetSurplus-(Double)itemMap.get("sellMediaActuallyPayment");
            factoryBudgetsurplus=factoryBudgetsurplus-(Double)itemMap.get("sellMediaExpenditure");
            itemMap.put("budgetSurplus",budgetSurplus);
            itemMap.put("factoryBudgetsurplus",factoryBudgetsurplus);
            itemMap.put("annualBudget",annualBudget);
        }
        return  list;
    }

    /**
     * 市场月度报表填报接口
     * @param infoList
     * @return
     */
    @Override
    @Transactional
    public ResultData updateMarketIntegrated(List <MarketIntegratedVO> infoList,String permit,String year) {
        Map map = new HashMap();
        List list = new ArrayList();
        try {
            if(infoList!=null&&infoList.size()!=0){
                //1.保存年度预算
                MarketAnnualBudgetModel marketAnnualBudgetModel;
                marketAnnualBudgetModel= marketAnnualBudgetRepository.findModelByPermitAndYear(permit,year);
                marketAnnualBudgetModel=  marketAnnualBudgetModel!=null?marketAnnualBudgetModel:new MarketAnnualBudgetModel();
                marketAnnualBudgetModel.setPermit(permit);
                marketAnnualBudgetModel.setStatDate(year);
                marketAnnualBudgetModel.setAnnualBudget(infoList.get(0).getAnnualBudget());
                marketAnnualBudgetRepository.save(marketAnnualBudgetModel);
                for (MarketIntegratedVO tempVo: infoList) {
                    MarketIntegratedReportModel marketIntegratedReportModel;
                    marketIntegratedReportModel=marketIntegratedReportRepository.findModelByPermitAndYear(permit,tempVo.getStatDate());
                    marketIntegratedReportModel=  marketIntegratedReportModel!=null?marketIntegratedReportModel:new MarketIntegratedReportModel();
                    marketIntegratedReportModel.setPermit(permit);
                    marketIntegratedReportModel.setStatDate(tempVo.getStatDate());
                    //售后厂家到账支援金
                    marketIntegratedReportModel.setAfterSaleActivitieFactorySupportFunds(tempVo.getAfterSaleActivitieFactorySupportFunds());
                    //售后当月活动执行费用
                    marketIntegratedReportModel.setAfterSaleActivitieExecuteExpenses(tempVo.getAfterSaleActivitieExecuteExpenses());
                    //售后当月活动实际支付
                    marketIntegratedReportModel.setAfterSaleActivitiePayment(tempVo.getAfterSaleActivitiePayment());
                    //售后当月活动展开数量（个）
                    marketIntegratedReportModel.setAfterSaleActivitiesNum(tempVo.getAfterSaleActivitiesNum());
                    //售后厂家到账支援金
                    marketIntegratedReportModel.setAfterSaleMediaFactorySupportFunds(tempVo.getAfterSaleMediaFactorySupportFunds());
                    //售后当月广宣执行费用
                    marketIntegratedReportModel.setAfterSaleMediaPublicityExpenses(tempVo.getAfterSaleMediaPublicityExpenses());
                    //售后当月媒体实际支付
                    marketIntegratedReportModel.setAfterSaleMediaActuallyPayment(tempVo.getAfterSaleMediaActuallyPayment());
                    //销售厂家到账支援金
                    marketIntegratedReportModel.setSellActivitieFactorySupportFunds(tempVo.getSellActivitieFactorySupportFunds());
                    //销售当月活动执行费用
                    marketIntegratedReportModel.setSellActivitieExecuteExpenses(tempVo.getSellActivitieExecuteExpenses());
                    //销售当月活动实际支付
                    marketIntegratedReportModel.setSellActivitiePayment(tempVo.getSellActivitiePayment());
                    //销售当月活动展开数量（个）
                    marketIntegratedReportModel.setSellActivitiesNum(tempVo.getSellActivitiesNum());
                    //销售厂家到账支援金
                    marketIntegratedReportModel.setSellMediaFactorySupportFunds(tempVo.getSellMediaFactorySupportFunds());
                    //销售当月广宣执行费用
                    marketIntegratedReportModel.setSellMediaPublicityExpenses(tempVo.getSellMediaPublicityExpenses());
                    //销售当月媒体实际支付
                    marketIntegratedReportModel.setSellMediaActuallyPayment(tempVo.getSellMediaActuallyPayment());
                    marketIntegratedReportRepository.save(marketIntegratedReportModel);
                }
            }
        } catch (Exception e) {
            logger.error("市场月度报表填报异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new ResultData("false", "填报异常,请重试");
        }
        return new ResultData("true", "保存成功");
    }

    //---------------------市场月度报表end  -----------------------------
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getSalesFunnel(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);

        context.setHandler(SalesFunnelRowHandler);

        //获取报表指标树:Y轴维度
        List<ReportConfig> configs = getReportConifTree("销售漏斗");
        // 设置开始月份和结束月份
        if ((null != info.get("startDay")) && (null != info.get("endDay"))) {
            String startMonth = info.get("startDay").toString().substring(0,7).replace("-","");
            String endMonth = info.get("endDay").toString().substring(0,7).replace("-","");
            info.put("startMonth",startMonth);
            info.put("endMonth",endMonth);
            context.setParams(info);
        }
        return reportDataService.getData(context, configs, salesFunnelDataSource);
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getFinanceFunnel(Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportContext(info);
        //获取报表指标树:Y轴维度
        List<ReportConfig> configs = getReportConifTree("金融漏斗");

        // 设置开始月份和结束月份
        if ((null != info.get("startDay")) && (null != info.get("endDay"))) {
            String startMonth = info.get("startDay").toString().substring(0,7).replace("-","");
            String endMonth = info.get("endDay").toString().substring(0,7).replace("-","");
            info.put("startMonth",startMonth);
            info.put("endMonth",endMonth);
            context.setParams(info);
        }

        context.setHandler(new FinancialFunnelRowHandler());
        List list =  reportDataService.getData(context, configs, financeFunnelDataSource);
        if ("5".equals(info.get("displayType"))) {
            specialFinanceFunnel(list);
        }
        return list;
    }

    private void specialFinanceFunnel (List list) {
        if (list != null) {
            for (Object o : list) {
                Map map = (Map) o;
                if (("进店线索数".equals(map.get("projectName")) || "开票数".equals(map.get("projectName")) ||"订单数".equals(map.get("projectName")))
                        && !"总计".equals(map.get("displayRow"))) {
                    map.put("projectValue", "");
                }
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getSaleGoal(Map info) throws Exception{
        List<Map> list=new ArrayList<>();
        int c=1;
        for (int a=0;a<groups.length;a++){
            for (int b=0;b<carType.length;b++,c++){
                    Map map=new LinkedHashMap();
                    map.put("displayRowone",groups[a]);//一级扩展列表名，值为xx大区总计及经销商名称 string
                    map.put("displayRowoneOrder",c);//displayRowone的排序依据  int
                    map.put("displayRowbrand",carType[b]);//横向一级扩展列表名，值为品牌名称 String
                    map.put("displayRowbrandOrder",c);//displayRowbrand的排序依据 int
                    map.put("groupGoals",(200+c));//集团目标值 int
                    map.put("groupGoalsOrder",(c));//集团目标值的排序依据 int
                    map.put("regionGoals",(220+c));//区域目标值 int
                    map.put("regionGoalsOrder",(c));//区域目标值的排序依据 int
                    map.put("regionGoalssrate",(88+c)+"%");//区域目标值达成率 string
                    map.put("regionGoalssrateOrder",(c));//区域目标值达成率的排序依据 int
                    list.add(map);
            }
        }
        c=0;
        return list;
    }
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public List getFinancialServiceFeeRateReport(FinancialServiceFeeRateReport reportVo) throws Exception {
        Map info=makeSearchArea(reportVo);
        if(reportVo.beginRatio!=null){
            info.put("beginRatio",reportVo.beginRatio);
        }
        if(reportVo.endRatio!=null){
            info.put("endRatio",reportVo.endRatio);
        }
        Map <String ,Map>regionDataMap=new HashMap();
        Map <String ,Map>pmaDataMap=new HashMap();
        //获取所有大区的服务费比例值
        List regionDataList=marketIntegrateRepository.getFinanceServiceFeeRateRegionForDCH(info);
        for(Object temp:regionDataList){
            Map tempMap=(Map) temp;
            regionDataMap.put(String.valueOf(tempMap.get("b_region_code")),tempMap);
        }
  /*      //获取所有PMA的服务费比例值
        List pmaDataList=marketIntegrateRepository.getFinanceServiceFeeRatePMA(info);
        for(Object temp:pmaDataList){
            Map tempMap=(Map) temp;
            pmaDataMap.put(String.valueOf(tempMap.get("pma")),tempMap);
        }*/
        //获取当前搜索范围的经销商服务费比例值
        List dealerDataList=marketIntegrateRepository.getFinanceServiceFeeRateForDCH(info);
        for(Object temp:dealerDataList){
            Map tempMap=(Map) temp;
            String region=String.valueOf(tempMap.get("b_region_code"));
        /*    String pma=String.valueOf(tempMap.get("pma"));*/
            Map regionData=regionDataMap.get(region);
            if(regionData==null)
            {
                tempMap.put("region", "  ");
                tempMap.put("b_region_code", "  ");
                tempMap.put("regionaverageratio", 0);
            }else {
                tempMap.put("regionaverageratio", regionData.get("financialServiceFeeRate"));
            }
      /*      Map pmaData=regionDataMap.get(pma);
            tempMap.put("pmaAverageRatio",regionData.get("financialServiceFeeRate"));*/
        }
        return dealerDataList;
    }

    /**
     * 查询市场活动列表
     * @param info
     * @return
     */
    @Override
    public PageData getMargetingActivityReoprt (Map info) throws Exception {
        List resultList = null;
        String area = null, pma = null, dealer = null, series = null, lead = null, selBrand = null, level = null,
                staDate = null, endDate = null, export = null, page = null;
        if (StringUtils.isNotNullOrBlank(info.get("area")) && !"全部".equals(info.get("area")) && !"all".equals(info.get("area"))) {
            area = info.get("area").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("PMA")) && !"全部".equals(info.get("PMA")) && !"all".equals(info.get("PMA"))) {
            pma = info.get("PMA").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("Dealer")) && !"全部".equals(info.get("Dealer")) && !"all".equals(info.get("Dealer"))) {
            dealer = info.get("Dealer").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("series")) && !"全部".equals(info.get("series")) && !"all".equals(info.get("series"))) {
            series = info.get("series").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("lead")) && !"全部".equals(info.get("lead")) && !"all".equals(info.get("lead"))) {
            lead = info.get("lead").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("selBrand")) && !"全部".equals(info.get("selBrand")) && !"all".equals(info.get("selBrand"))) {
            selBrand = info.get("selBrand").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("Ftype")) && !"全部".equals(info.get("Ftype")) && !"all".equals(info.get("Ftype"))) {
            level = info.get("Ftype").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("STADATE")) && !"全部".equals(info.get("STADATE")) && !"all".equals(info.get("STADATE"))) {
            staDate = info.get("STADATE").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("ENDDATE")) && !"全部".equals(info.get("ENDDATE")) && !"all".equals(info.get("ENDDATE"))) {
            endDate = info.get("ENDDATE").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("export")) && !"全部".equals(info.get("export")) && !"all".equals(info.get("export"))) {
            export = info.get("export").toString();
        }
        if (StringUtils.isNotNullOrBlank(info.get("page")) && !"全部".equals(info.get("page")) && !"all".equals(info.get("page"))) {
            page = info.get("page").toString();
        }

        //没有else这里的else是干嘛的？

//        else {
//
//        }

        PageData pageData = marketIntegrateRepository.getMargetingActivityList(area, pma, dealer, series, lead, selBrand, level,
                staDate, endDate, export, Integer.parseInt(page) - 1, 15);
        List kpiList = marketIntegrateRepository.getMargetingActivityKPIData(staDate, endDate, export);
        if (pageData != null) {
            List list = afterTreatmentMargetingActivityData(pageData, kpiList, export);
            pageData.setTotal(pageData.getTotal() / 15 + 1);
            pageData.setData(list);
        }
        return pageData;
    }

    /**
     * 组装市场活动KPI信息
     * @param pageData
     * @param list
     * @return
     */
    private List afterTreatmentMargetingActivityData (PageData pageData, List list, String export) {
        List resultList = new ArrayList();
        if (pageData.getData() != null) {
            Map<String, Integer> actMap = new HashMap<>();
            actMap.put("活动编号", 0);
            actMap.put("创建日期", 1);
            actMap.put("活动名称", 2);
            actMap.put("主导与发起", 3);
            actMap.put("活动类型", 4);
            actMap.put("主推车系", 5);
            actMap.put("开始日期", 6);
            actMap.put("结束日期", 7);
            actMap.put("经销商名", 8);
            actMap.put("CTA", 9);
            actMap.put("大区", 10);
            actMap.put("状态", 11);

            //区分出 必选KPI、可选KPI、未启用KPI，并分别放入对应的Map中
            Map<String, Object> rquiredKPIMap = new HashMap<>(),
                    optionKPIMap = new HashMap<>(),
                    notEnabledKPIMap = new HashMap<>(),
                    kpiDataMap = new HashMap<>();
            for (Object o : list) {
                Map map = (Map) o;
                //KPI的活动状态作为KPI类型的区分标准
                if ("活动必选KPI".equals(map.get("活动状态"))) {
                    if (map.get("KPI") != null) {
                        rquiredKPIMap.put(map.get("KPI").toString(), map.get("KPI"));
                    }
                } else if ("活动可选KPI".equals(map.get("活动状态"))) {
                    if (map.get("KPI") != null) {
                        optionKPIMap.put(map.get("KPI").toString(), map.get("KPI"));
                    }
                } else if ("未启用KPI".equals(map.get("活动状态"))) {
                    if (map.get("KPI") != null) {
                        notEnabledKPIMap.put(map.get("KPI").toString(), map.get("KPI"));
                    }
                }
                if (StringUtils.isNotNullOrBlank(map.get("活动编号"))
                        && StringUtils.isNotNullOrBlank(map.get("活动状态"))
                        && StringUtils.isNotNullOrBlank(map.get("KPI"))) {
                    String kpiDataKey = map.get("活动编号") + "_" + map.get("活动状态") + "_" + map.get("KPI");
                    int kpiDataValue = 0, value = 0;
                    if (StringUtils.isNotNullOrBlank(kpiDataMap.get(kpiDataKey))) {
                        kpiDataValue = Integer.parseInt(String.valueOf(kpiDataMap.get(kpiDataKey)));
                    }
                    if (StringUtils.isNotNullOrBlank(map.get("kpi_value"))) {
                        value = Integer.parseInt(String.valueOf(map.get("kpi_value")));
                    }
                    kpiDataMap.put(kpiDataKey, kpiDataValue + value);
                }
            }

            //遍历查询出的市场活动信息，匹配每个市场活动对应的必选KPI、可选KPI、未启用KPI名称及KPI值
            int displayRow = 1, displayColumn;
            for (Object baseO : pageData.getData()) {
                displayColumn = 1;
                Map baseMap = (Map) baseO;
                String actId = baseMap.get("活动编号").toString();
                for (Object baseKey : baseMap.keySet()) {
                    if (actMap.get(baseKey.toString()) != null && actMap.get(baseKey.toString()) == 0) {
                        continue;
                    }
                    resultList.add(getDataMap(displayRow, actMap.get(baseKey.toString()), baseKey, null, null, null, baseMap.get(baseKey)));
                    displayColumn++;
                }
                for (String rquiredKPIKey : rquiredKPIMap.keySet()) {
                    resultList.add(getDataMap(displayRow, displayColumn, rquiredKPIKey, "活动必选KPI", null, null, kpiDataMap.get(actId + "_活动必选KPI_" + rquiredKPIKey)));
                    displayColumn++;
                }
                if (!"1".equals(export)) {
                    for (String optionKPIKey : optionKPIMap.keySet()) {
                        resultList.add(getDataMap(displayRow, displayColumn, optionKPIKey, null, "活动可选KPI", null, kpiDataMap.get(actId + "_活动可选KPI_" + optionKPIKey)));
                        displayColumn++;
                    }
                    for (String notEnabledKPIKey : notEnabledKPIMap.keySet()) {
                        resultList.add(getDataMap(displayRow, displayColumn, notEnabledKPIKey, null, null, "未启用KPI", kpiDataMap.get(actId + "_未启用KPI_" + notEnabledKPIKey)));
                        displayColumn++;
                    }
                }
                displayRow++;
            }
        }
        return resultList;
    }

    @Override
    public List getSalesDailyReport (Map info) throws Exception {
        //构造context ：包括权限等级，x轴的维度（时间维度，组织架构维度）
        ReportContext context= LineContextUtil.getReportDayLineContext(info);
        //获取报表指标树:Y轴维度
        List<ReportConfig> configs = getReportConifTree("SalesDaily");
        List list =  reportDataService.getData(context, configs, SalesDailyReportSource);
        return list;
    }

    private  Map makeSearchArea(FinancialServiceFeeRateReport reportVo){
        Map params=new HashMap();
        //1.判断时间搜索周期
        if(!Strings.isNullOrEmpty(reportVo.selMonth)&&!"all".equalsIgnoreCase(reportVo.selMonth)){
            if(reportVo.selMonth.length()<2){
                params.put("startDate",reportVo.selectYear+"0"+reportVo.selMonth);
                params.put("endDate",reportVo.selectYear+"0"+reportVo.selMonth);
            }else{
                params.put("startDate",reportVo.selectYear+reportVo.selMonth);
                params.put("endDate",reportVo.selectYear+reportVo.selMonth);
            }

        }
        else if(!Strings.isNullOrEmpty(reportVo.selQuarter)&&!"all".equalsIgnoreCase(reportVo.selQuarter)){
            if("1".equalsIgnoreCase(reportVo.selQuarter)){
                params.put("startDate",reportVo.selectYear+"01");
                params.put("endDate",reportVo.selectYear+"03");
            }
            if("2".equalsIgnoreCase(reportVo.selQuarter)){
                params.put("startDate",reportVo.selectYear+"04");
                params.put("endDate",reportVo.selectYear+"06");
            }
            if("3".equalsIgnoreCase(reportVo.selQuarter)){
                params.put("startDate",reportVo.selectYear+"07");
                params.put("endDate",reportVo.selectYear+"09");
            }
            if("4".equalsIgnoreCase(reportVo.selQuarter)){
                params.put("startDate",reportVo.selectYear+"10");
                params.put("endDate",reportVo.selectYear+"12");
            }
        }else{
            params.put("startDate",reportVo.selectYear+"01");
            params.put("endDate",reportVo.selectYear+"12");
        }
        //2.判断区域
          //a.账号为 admin 且为 all
        if(!Strings.isNullOrEmpty(reportVo.selDealerCode)&&"all".equalsIgnoreCase(reportVo.selDealerCode)&&"admin".equalsIgnoreCase(reportVo.username)){
            params.put("permit","DCH");
        }
        else if ( !Strings.isNullOrEmpty(reportVo.selDealerCode)&&!"all".equalsIgnoreCase(reportVo.selDealerCode)) {
            String permitLSH = reportVo.selDealerCode; //许可lsh
            // 许可lsh转为许可_BMBS
            String permitBMBS = lsh经销商表Repository.getDistributorByPermitLSH(permitLSH).get(0).getBmbs();  // 开发库中，经销商表有经销商重复的脏数据，使用get(0)
            params.put("permit",permitBMBS);
        } else if (!Strings.isNullOrEmpty(reportVo.selPMACode)&&!"all".equalsIgnoreCase(reportVo.selPMACode)  ) {
            params.put("permit",reportVo.selPMACode);
        } else if ( !Strings.isNullOrEmpty(reportVo.selRegionCode)&&!"all".equalsIgnoreCase( reportVo.selRegionCode) ) {
            params.put("permit", reportVo.selRegionCode);
        } else {
            params.put("permit",userRepository.findPermitByUsername(reportVo.username));
        }
        return  params;
    }

    private Map<String, Object> getDataMap (int displayRowOrder, int displayColumnOrder, Object displayColumnName,
                                            Object rquiredKPIName, Object optionKPIName, Object notEnabledKPIName, Object displayValue) {
        Map<String, Object> resultMap = new HashMap<>();
        //行序号
        resultMap.put("displayRowOrder", displayRowOrder);
        //列序号
        resultMap.put("displayColumnOrder", displayColumnOrder);
        //列名
        resultMap.put("displayColumnName", displayColumnName);
        //KPI类型--必选KPI
        resultMap.put("rquiredKPIName", rquiredKPIName);
        //KPI类型--可选KPI
        resultMap.put("optionKPIName", optionKPIName);
        //KPI类型--未启用KPI
        resultMap.put("notEnabledKPIName", notEnabledKPIName);
        //KPI值
        resultMap.put("displayValue", displayValue);
        return resultMap;
    }

    private List<StockForecastVo> buildHighlightReport(Map info){
        String brand = String.valueOf(info.get("selBrand"));
        String carSeries = String.valueOf(info.get("selClass"));
        String carModel = String.valueOf(info.get("selType"));
        String permit = String.valueOf(userRepository.findPermitByUsername(info.get("fr_username").toString()));
        List<StockForecastVo> list = new ArrayList<StockForecastVo>();
        List<ReportConfig> configList = buildReportFormTitle(DefaultValueConstant.REPORT_FORM_GROSS_PROFIT_FORECAST_HIGHLIGHT_TYPE);
        for (int i = 0; i < configList.size(); i ++) {
            ReportConfig config = configList.get(i);
            StockForecastVo vo = null;
            if(config.getText().equals("车型")){
                vo = new StockForecastVo(config.getText(),null,Integer.parseInt(config.getProjectNameOrder()),0,carModel,config.getReportCode());
            }else{
                vo = new StockForecastVo(config.getText(),null,Integer.parseInt(config.getProjectNameOrder()),0,StockForecastUtils.orderFormValue(config.getText(),brand,carSeries,carModel,permit),config.getReportCode());
            }
            list.add(vo);
        }
        return list;

    }


    /**
     * 组建毛利预测主体
     * @param info
     * @return
     */
    private Map<String,Object> getTotalFormByGrossProfit(Map info){
        Map<String,Object> map = Maps.newHashMap();
        //毛利预测计划分为6个分开的小报表①高亮显示数据②库存管理③漏斗管理④新车毛利管理⑤衍生业务管理⑥综合毛利
        //高亮显示数据
        map.put("highlightReport",buildOrderReport(info));
        //库存管理
        map.put("stockReport",replaceMap(buildColorReport(info)));
        //漏斗管理
        map.put("funnelReport",replaceMap(buildCarReport(info)));
        //新车毛利管理
        map.put("newGrossProfitReport",buildPurchaseReport(info));
        //衍生业务管理
        map.put("otherReport",buildPurchaseReport(info));
        //综合毛利
        map.put("comprehensiveGrossProfitReport",buildPurchaseReport(info));
        return map;
    }

    private void replaceAfterMarketReportList(List<Map> list){
        //业务报表由两个指标确定（产品种类，采购来源）
        list.stream()
                .forEach(e->{
                    if(e.get("threeIndexName")!=null)
                    e.put("threeIndexName",e.get("threeIndexName").toString().split("_")[0]);
                            });
    }
}
